﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews.Application.Controls
{
    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;

    /// <summary>Contains entry points to all native methods.</summary>
    internal static class NativeMethods
    {
        internal const int GWL_WNDPROC = -4;

        // Windows messages
        internal const uint WM_CONTEXTMENU = 0x007B;
        internal const uint WM_LBUTTONDOWN = 0x0201;
        internal const uint WM_NOTIFY = 0x4E;

        // Key State Masks
        internal const uint MK_LBUTTON = 0x0001;

        private const uint TV_FIRST = 0x1100;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal delegate int WndProc(IntPtr hwnd, uint msg, uint wParam, int lParam);

        [DllImport("coredll.dll", SetLastError = true)]
        internal static extern IntPtr SetWindowLong(IntPtr hwnd, int nIndex, IntPtr dwNewLong);

        [DllImport("coredll.dll")]
        internal static extern int CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hwnd, uint msg, uint wParam, int lParam);

        [DllImport("coredll.dll")]
        internal static extern int DefWindowProc(IntPtr hwnd, uint msg, uint wParam, int lParam);

        internal enum TVM_GETITEMRECT : uint
        {
            MSG = TV_FIRST + 4
        }

        /// <summary>See <a href="http://msdn.microsoft.com/en-us/library/aa932309.aspx">RECT</a>..</summary>
        internal struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [DllImport("coredll.dll", SetLastError = true)]
        internal static extern int SendMessage(IntPtr hwnd, TVM_GETITEMRECT msg, uint wParam, ref RECT lParam);

        internal enum TVM_HITTEST : uint
        {
            MSG = TV_FIRST + 17
        }

        /// <summary>See <a href="http://msdn.microsoft.com/en-us/library/ms911930.aspx">POINT</a>.</summary>
        internal struct POINT
        {
            internal POINT(int x, int y)
            {
                this.X = x;
                this.Y = y;
            }

            internal readonly int X;
            internal readonly int Y;
        }

        [Flags]
        internal enum TVHT : uint
        {
            ONITEMICON = 0x0002,
            ONITEMLABEL = 0x0004,
            ONITEM = ONITEMICON | ONITEMLABEL | ONITEMSTATEICON,
            ONITEMSTATEICON = 0x0040
        }

        /// <summary>See <a href="http://msdn.microsoft.com/en-us/library/aa931266.aspx">TVHITTESTINFO</a>.</summary>
        internal struct TVHITTESTINFO
        {
            internal readonly POINT pt;
            internal readonly TVHT flags;
            internal readonly IntPtr hItem;

            internal TVHITTESTINFO(int x, int y)
            {
                this.pt = new POINT(x, y);
                this.flags = 0;
                this.hItem = IntPtr.Zero;
            }
        }

        [DllImport("coredll.dll")]
        internal static extern int SendMessage(IntPtr hwnd, TVM_HITTEST msg, uint wParam, ref TVHITTESTINFO lParam);

        internal enum TVM_SELECTITEM : uint
        {
            MSG = TV_FIRST + 11
        }

        internal enum TVGN : uint
        {
            CARET = 0x0009
        }

        [DllImport("coredll.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SendMessage(IntPtr hwnd, TVM_SELECTITEM msg, TVGN wParam, IntPtr lParam);

        internal enum TVM_SETITEMW : uint
        {
            MSG = TV_FIRST + 63
        }

        [Flags]
        internal enum TVIF : uint
        {
            IMAGE         = 0x0002,
            STATE         = 0x0008,
            HANDLE        = 0x0010,
            SELECTEDIMAGE = 0x0020
        }

        [Flags]
        internal enum TVIS : uint
        {
            BOLD = 0x0010,
        }

        /// <summary>See <a href="http://msdn.microsoft.com/en-us/library/aa931032.aspx">TVITEM</a>.</summary>
        internal struct TVITEM
        {
            private readonly TVIF mask;
            private readonly IntPtr hItem;
            private readonly TVIS state;
            private readonly TVIS stateMask;
            [MarshalAs(UnmanagedType.LPWStr)]
            private readonly string pszText;
            private readonly int cchTextMax;
            private readonly int iImage;
            private readonly int iSelectedImage;
            private readonly int cChildren;
            private readonly int lParam;

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////

            internal TVITEM(IntPtr nodeHandle, bool bold, int imageIndex, int selectedImageIndex)
            {
                this.mask = TVIF.IMAGE | TVIF.STATE | TVIF.HANDLE | TVIF.SELECTEDIMAGE;
                this.hItem = nodeHandle;
                this.state = bold ? TVIS.BOLD : 0;
                this.stateMask = TVIS.BOLD;
                this.pszText = null;
                this.cchTextMax = 0;
                this.iImage = imageIndex;
                this.iSelectedImage = selectedImageIndex;
                this.cChildren = 0;
                this.lParam = 0;
            }
        }

        [DllImport("coredll.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SendMessage(IntPtr hwnd, TVM_SETITEMW msg, uint wParam, ref TVITEM lParam);

        /// <summary>See <a href="http://msdn.microsoft.com/en-us/library/aa923120.aspx">SHRGINFO</a>.</summary>
        [StructLayout(LayoutKind.Sequential)]
        internal class SHRGINFO
        {
            private const uint SHRG_RETURNCMD = 0x00000001;

            private readonly uint cbSize;
            private readonly IntPtr hwndClient;
            private readonly int x;
            private readonly int y;
            private readonly uint dwFlags;

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////

            internal SHRGINFO(IntPtr hwndClient, int x, int y)
            {
                this.cbSize = (uint)Marshal.SizeOf(this);
                this.hwndClient = hwndClient;
                this.x = x;
                this.y = y;
                this.dwFlags = SHRG_RETURNCMD;
            }
        }

        [DllImport("aygshell.dll")]
        internal static extern uint SHRecognizeGesture(SHRGINFO shrgInfo);

        internal static Point LParamToPoint(int lParam)
        {
            uint ulParam = (uint)lParam;
            return new Point((int)(ulParam & 0x0000ffff), (int)((ulParam & 0xffff0000) >> 16));
        }
    }
}
